
package com.avicit.zipkinkafkaesserver.controller;

import com.avicit.zipkinkafkaesserver.service.SparkService;
import com.avicit.zipkinkafkaesserver.service.ZipkinInterfaceAverageDurationService;
import com.avicit.zipkinkafkaesserver.service.ZipkinInterfaceCountService;
import com.avicit.zipkinkafkaesserver.utils.TimeUtils;
import com.avicit.zipkinkafkaesserver.vo.InterfaceCountVo;
import com.avicit.zipkinkafkaesserver.vo.RealtimeAvgDurationChartDataKvVo;
import com.avicit.zipkinkafkaesserver.vo.RealtimeAvgDurationChartDataVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import scala.Tuple2;

import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * es 对应的查询接口
 */
@RestController
@RequestMapping("/zipkin")
public class ZipKinESController {

    //接口平均耗时
    @Autowired
    private ZipkinInterfaceAverageDurationService zipkinInterfaceAverageDurationService;

    @Autowired
    private SparkService sparkService;

    /**
     * 实时数据查询 from es 接口实时调用
     * top 100
     * 默认查询 1 天的
     * queryDate 日期 2019-06-11
     * startTime 开始时间 09:00:00
     * endTime 结束时间  09:15:00
     * @param serverName  服务名
     * @param interfaceName  接口名
     * @param model
     * @return
     */

    @RequestMapping("/interfaceCount")
    public List<InterfaceCountVo> interfaceCount(
                                 @RequestParam String queryDate,
                                 @RequestParam String startTime,
                                 @RequestParam String endTime,
                                 @RequestParam(required = false) String serverName,
                                 @RequestParam(required = false) String interfaceName) throws IOException {


        long currentTimeMillis = System.currentTimeMillis();
        queryDate = queryDate == null ? TimeUtils.nowDateString() : queryDate;

        long startTimeSecond = 0;
        long endTimesecond = 0;

        if (!StringUtils.isEmpty(startTime) && !StringUtils.isEmpty(endTime)&& !startTime.equals(endTime)) {
            // 日期 + 时间 2019-06-11 09:00:00
            StringBuilder sbStartTime = new StringBuilder(queryDate).append(" ").append(startTime);
            StringBuilder sbEndTime = new StringBuilder(queryDate).append(" ").append(endTime);
            startTimeSecond = TimeUtils.dateTimeToMilliSecond(sbStartTime.toString(), TimeUtils.DatePattern.ALLTIME);
            endTimesecond = TimeUtils.dateTimeToMilliSecond(sbEndTime.toString(), TimeUtils.DatePattern.ALLTIME);
        } else {
            endTimesecond = currentTimeMillis;//为空 取当前时间
            //为空取当前时间前 5分钟
            startTimeSecond = currentTimeMillis - 5*60*1000;
        }
        List<Tuple2<String, Integer>> tuple2List = sparkService.interfaceCountHasStatus(startTimeSecond,endTimesecond,100, serverName,interfaceName);

        Map<String,Integer> okMap = new HashMap<>();
        Map<String,Integer> errorMap = new HashMap<>();
        Set<String>pathSet = new HashSet<>();
        tuple2List.stream().forEach(item->{
            //server-a@GET@/getInfo@ok
            String key = item._1;
            //server-a@GET@/getInfo
            String path = key.substring(0,key.lastIndexOf("@"));
            // ok
            String status = key.substring(key.lastIndexOf("@")+1);
            //统计正确的和错误的
            if ("ok".equals(status)) {okMap.put(path,item._2);}
            if ("error".equals(status)){errorMap.put(path,item._2);}
            pathSet.add(path);
        });
        List<InterfaceCountVo> countVos = new ArrayList<>();

        //从两个map 集合去取数据
        for (String key : pathSet) {
            //server-a@GET@/getInfo
            String[] split = key.split("@");
            Integer okCount = okMap.get(key);
            Integer errorCount = errorMap.get(key);
            okCount  = okCount==null?0: okCount;
            errorCount = errorCount ==null?0: errorCount;
            InterfaceCountVo countVo = InterfaceCountVo.builder()
                    .errorCount(errorCount)
                    .serverName(split[0])
                    .interfaceName(split[2])
                    .count(okCount + errorCount).build();
            countVos.add(countVo);
        }
        return countVos.stream().sorted(Comparator.comparing(InterfaceCountVo::getCount).reversed()).collect(Collectors.toList());
    }

    /**
     * 实时接口平均耗时
     * @return
     * @throws IOException
     */
    @RequestMapping("/interfaceAvgDuration")
    public  List<InterfaceCountVo> interfaceDurationCount(@RequestParam String queryDate,
                                         @RequestParam String startTime,
                                         @RequestParam String endTime,
                                         @RequestParam(required = false) String serverName,
                                         @RequestParam(required = false) String interfaceName
    ) throws IOException {
        long currentTimeMillis = System.currentTimeMillis();
        queryDate = queryDate == null ? TimeUtils.nowDateString() : queryDate;

        long startTimeSecond = 0;
        long endTimesecond = 0;

        if (!StringUtils.isEmpty(startTime) && !StringUtils.isEmpty(endTime)&& !startTime.equals(endTime)) {
            // 日期 + 时间 2019-06-11 09:00:00
            StringBuilder sbStartTime = new StringBuilder(queryDate).append(" ").append(startTime);
            StringBuilder sbEndTime = new StringBuilder(queryDate).append(" ").append(endTime);
            startTimeSecond = TimeUtils.dateTimeToMilliSecond(sbStartTime.toString(), TimeUtils.DatePattern.ALLTIME);
            endTimesecond = TimeUtils.dateTimeToMilliSecond(sbEndTime.toString(), TimeUtils.DatePattern.ALLTIME);
        } else {
            endTimesecond = currentTimeMillis;//为空 取当前时间
            //为空取当前时间前 5分钟
            startTimeSecond = currentTimeMillis - 5*60*1000;
        }

        List<Tuple2<String, Double>> tuple2s = (List<Tuple2<String, Double>>)sparkService.interfaceDurationCountNoIp(startTimeSecond,endTimesecond,100,serverName,interfaceName).get("countResult");
        List<InterfaceCountVo> countVos = tuple2s.stream().map(tuple2 -> {
            String[] split = tuple2._1.split("@");
            double value = tuple2._2;
            return InterfaceCountVo.builder()
//                    .ip(split[0])
                    .serverName(split[0])
                    .interfaceName(split[2])
                    .duration((int) value)
                    .build();
            //倒排
        }).sorted(Comparator.comparing(InterfaceCountVo::getDuration).reversed()).collect(Collectors.toList());
        return countVos;
    }

    /**
     * 实时接口耗时列表, 接口调用明细 es
     * @return
     */
    @RequestMapping("/interfaceDurationCountList")
    public List<InterfaceCountVo> interfaceDurationCountList(@RequestParam String queryDate,
                                             @RequestParam String startTime,
                                             @RequestParam String endTime,
                                             @RequestParam String serverName,
                                             @RequestParam String interfaceName
    ) throws IOException {
        long currentTimeMillis = System.currentTimeMillis();
        queryDate = queryDate == null ? TimeUtils.nowDateString() : queryDate;

        long startTimeSecond = 0;
        long endTimesecond = 0;

        if (!StringUtils.isEmpty(startTime) && !StringUtils.isEmpty(endTime)&& !startTime.equals(endTime)) {
            // 日期 + 时间 2019-06-11 09:00:00
            StringBuilder sbStartTime = new StringBuilder(queryDate).append(" ").append(startTime);
            StringBuilder sbEndTime = new StringBuilder(queryDate).append(" ").append(endTime);
            startTimeSecond = TimeUtils.dateTimeToMilliSecond(sbStartTime.toString(), TimeUtils.DatePattern.ALLTIME);
            endTimesecond = TimeUtils.dateTimeToMilliSecond(sbEndTime.toString(), TimeUtils.DatePattern.ALLTIME);
        } else {
            endTimesecond = currentTimeMillis;//为空 取当前时间
            //为空取当前时间前 5分钟
            startTimeSecond = currentTimeMillis - 5*60*1000;
        }
        List<Tuple2<String, Double>> tuple2s = sparkService.interfaceDurationCountList(startTimeSecond, endTimesecond,100,serverName,interfaceName);
        List<InterfaceCountVo> countVos = tuple2s.stream().map(tuple2 -> {
            String[] split = tuple2._1.split("@");
            double value = tuple2._2;
            return InterfaceCountVo.builder()
                    .ip(split[0])
                    .serverName(split[1])
                    .interfaceName(split[3])
                    .status(split[4])
                    .dateTime(TimeUtils.timestamToDatetime(Long.valueOf(split[5])))
                    .duration((int) value)
                    .build();
            //倒排
        }).sorted(Comparator.comparing(InterfaceCountVo::getDuration).reversed()).collect(Collectors.toList());
        return countVos;
    }

    /**
     * 图标数据查询 列表
     * @param queryDateFrom 开始日期
     * @param queryDateTo 结束日期
     * @param serverName 服务名
     * @param interfacePath 服务接口
     * @return
     */
    @RequestMapping("/realtimeAvgDurationChartData")
    @ResponseBody
    public List<RealtimeAvgDurationChartDataVo> getRealtimeAvgDurationChartDataKv(
            @RequestParam String queryDateFrom,
            @RequestParam String queryDateTo,
            @RequestParam String serverName,
            @RequestParam String interfacePath
    ) throws IOException {
        List<RealtimeAvgDurationChartDataVo> result = zipkinInterfaceAverageDurationService.getRealtimeAvgDurationChartData(queryDateFrom,queryDateTo,serverName,interfacePath);
        return result;
    }

    /**
     * 图标数据查询
     * @param queryDateFrom 开始日期
     * @param queryDateTo 结束日期
     * @param serverName 服务名
     * @param interfacePath 服务接口
     * @param model
     * @return
     */
    @RequestMapping("/realtimeAvgDurationChartDataKv")
    @ResponseBody
    public List<RealtimeAvgDurationChartDataKvVo> getRealtimeAvgDurationChartData(
            @RequestParam String queryDateFrom,
            @RequestParam String queryDateTo,
            @RequestParam String serverName,
            @RequestParam String interfacePath
    ) throws IOException {
        List<RealtimeAvgDurationChartDataVo> result = zipkinInterfaceAverageDurationService.getRealtimeAvgDurationChartData(queryDateFrom,queryDateTo,serverName,interfacePath);
        List<RealtimeAvgDurationChartDataKvVo> collect = result.stream().map(item ->
                RealtimeAvgDurationChartDataKvVo.builder().reqs(item.getReqs()/1000).time(item.getQueryStartTime()/1000).build()).collect(Collectors.toList());
        return collect;
    }
}
